<template>
  <div class="fixed top-4 left-0 right-0 z-9999 pointer-events-none">
    <div class="max-w-md mx-auto px-4 space-y-2">
      <div
        v-for="notification in notifications"
        :key="notification.id"
        class="notification-item pointer-events-auto transform transition-all duration-300 ease-out"
        :class="{
          'translate-y-0 opacity-100 scale-100': isVisible(notification.id),
          '-translate-y-full opacity-0 scale-95': !isVisible(notification.id),
        }"
        :style="getNotificationStyle()"
        @mouseenter="handleMouseEnter(notification.id)"
        @mouseleave="handleMouseLeave(notification.id)"
      >
        <div
          class="flex items-start p-4 rounded-lg shadow-lg"
          :style="getNotificationBackground(notification.type)"
        >
          <!-- 图标 -->
          <div class="shrink-0 mr-3">
            <svg
              class="w-6 h-6"
              :style="getIconColor(notification.type)"
              fill="currentColor"
              viewBox="0 0 20 20"
            >
              <!-- 成功图标 -->
              <path
                v-if="notification.type === 'success'"
                fill-rule="evenodd"
                d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
                clip-rule="evenodd"
              />
              <!-- 错误图标 -->
              <path
                v-else-if="notification.type === 'error'"
                fill-rule="evenodd"
                d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
                clip-rule="evenodd"
              />
              <!-- 警告图标 -->
              <path
                v-else-if="notification.type === 'warning'"
                fill-rule="evenodd"
                d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"
                clip-rule="evenodd"
              />
              <!-- 信息图标 -->
              <path
                v-else
                fill-rule="evenodd"
                d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
                clip-rule="evenodd"
              />
            </svg>
          </div>

          <!-- 内容 -->
          <div class="flex-1 min-w-0">
            <h4 class="text-sm font-medium" :style="getTitleColor(notification.type)">
              {{ notification.title }}
            </h4>
            <p
              v-if="notification.message"
              class="mt-1 text-sm"
              :style="getMessageColor(notification.type)"
            >
              {{ notification.message }}
            </p>
          </div>

          <!-- 关闭按钮 -->
          <div class="shrink-0 ml-4">
            <button
              @click="closeNotification(notification.id)"
              class="inline-flex rounded-md p-1 hover:bg-black/5 dark:hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-offset-1 transition-all duration-200"
              :style="getCloseButtonStyle(notification.type)"
              aria-label="关闭通知"
            >
              <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
                <path
                  fill-rule="evenodd"
                  d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
                  clip-rule="evenodd"
                />
              </svg>
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onUnmounted, watch, nextTick } from 'vue'
import { useNotification } from '@/composables/useNotification'
import type { Notification } from '@/composables/useNotification'

const { notifications, removeNotification, setAutoCloseCallback, pauseTimer, resumeTimer } =
  useNotification()

// 跟踪正在关闭的通知
const closingNotifications = ref<Set<string>>(new Set())

// 跟踪可见的通知状态
const visibleNotifications = ref<Set<string>>(new Set())

// 检查通知是否可见
function isVisible(id: string): boolean {
  return visibleNotifications.value.has(id) && !closingNotifications.value.has(id)
}

// 关闭通知（带动画）
function closeNotification(id: string) {
  startCloseAnimation(id)
}

// 通知样式
function getNotificationStyle() {
  const baseStyle = {
    borderRadius: '0.5rem',
    overflow: 'hidden',
  }

  return baseStyle
}

function getNotificationBackground(type: Notification['type']) {
  const isDark = document.documentElement.classList.contains('dark')

  switch (type) {
    case 'success':
      return {
        backgroundColor: isDark ? 'var(--success-900/20)' : 'var(--success-50)',
        border: `1px solid ${isDark ? 'var(--success-800/30)' : 'var(--success-200)'}`,
      }
    case 'error':
      return {
        backgroundColor: isDark ? 'var(--error-900/20)' : 'var(--error-50)',
        border: `1px solid ${isDark ? 'var(--error-800/30)' : 'var(--error-200)'}`,
      }
    case 'warning':
      return {
        backgroundColor: isDark ? 'var(--warning-900/20)' : 'var(--warning-50)',
        border: `1px solid ${isDark ? 'var(--warning-800/30)' : 'var(--warning-200)'}`,
      }
    case 'info':
    default:
      return {
        backgroundColor: isDark ? 'var(--primary-900/20)' : 'var(--primary-50)',
        border: `1px solid ${isDark ? 'var(--primary-800/30)' : 'var(--primary-200)'}`,
      }
  }
}

function getIconColor(type: Notification['type']) {
  const isDark = document.documentElement.classList.contains('dark')

  switch (type) {
    case 'success':
      return { color: isDark ? 'var(--success-300)' : 'var(--success-600)' }
    case 'error':
      return { color: isDark ? 'var(--error-300)' : 'var(--error-600)' }
    case 'warning':
      return { color: isDark ? 'var(--warning-300)' : 'var(--warning-600)' }
    case 'info':
    default:
      return { color: isDark ? 'var(--primary-300)' : 'var(--primary-600)' }
  }
}

function getTitleColor(type: Notification['type']) {
  const isDark = document.documentElement.classList.contains('dark')

  switch (type) {
    case 'success':
      return { color: isDark ? 'var(--success-200)' : 'var(--success-800)' }
    case 'error':
      return { color: isDark ? 'var(--error-200)' : 'var(--error-800)' }
    case 'warning':
      return { color: isDark ? 'var(--warning-200)' : 'var(--warning-800)' }
    case 'info':
    default:
      return { color: isDark ? 'var(--primary-200)' : 'var(--primary-800)' }
  }
}

function getMessageColor(type: Notification['type']) {
  const isDark = document.documentElement.classList.contains('dark')

  switch (type) {
    case 'success':
      return { color: isDark ? 'var(--success-300)' : 'var(--success-700)' }
    case 'error':
      return { color: isDark ? 'var(--error-300)' : 'var(--error-700)' }
    case 'warning':
      return { color: isDark ? 'var(--warning-300)' : 'var(--warning-700)' }
    case 'info':
    default:
      return { color: isDark ? 'var(--primary-300)' : 'var(--primary-700)' }
  }
}

function getCloseButtonStyle(type: Notification['type']) {
  const isDark = document.documentElement.classList.contains('dark')

  let color = ''
  let ringColor = ''

  switch (type) {
    case 'success':
      color = isDark ? 'var(--success-400)' : 'var(--success-600)'
      ringColor = isDark ? 'var(--success-500/50)' : 'var(--success-500/30)'
      break
    case 'error':
      color = isDark ? 'var(--error-400)' : 'var(--error-600)'
      ringColor = isDark ? 'var(--error-500/50)' : 'var(--error-500/30)'
      break
    case 'warning':
      color = isDark ? 'var(--warning-400)' : 'var(--warning-600)'
      ringColor = isDark ? 'var(--warning-500/50)' : 'var(--warning-500/30)'
      break
    case 'info':
    default:
      color = isDark ? 'var(--primary-400)' : 'var(--primary-600)'
      ringColor = isDark ? 'var(--primary-500/50)' : 'var(--primary-500/30)'
  }

  return {
    color,
    '--tw-ring-color': ringColor,
  }
}

// 监听新通知
watch(
  notifications,
  (newNotifications, oldNotifications) => {
    // 找出新增的通知
    const oldIds = new Set(oldNotifications?.map((n) => n.id) || [])

    newNotifications.forEach((notification) => {
      // 只处理新添加的通知
      if (!oldIds.has(notification.id) && !visibleNotifications.value.has(notification.id)) {
        // 立即添加到可见通知集合
        visibleNotifications.value.add(notification.id)

        // 使用 nextTick 确保通知已渲染
        nextTick(() => {
          // 在通知渲染后设置自动关闭回调
          if (notification.duration && notification.duration > 0) {
            setAutoCloseCallback(notification.id, () => {
              startCloseAnimation(notification.id)
            })
          }
        })
      }
    })
  },
  { deep: true, immediate: true }, // 立即执行一次，处理初始通知
)

// 组件卸载时清理资源
onUnmounted(() => {
  // 清理所有正在关闭和可见的通知状态
  closingNotifications.value.clear()
  visibleNotifications.value.clear()

  // 不在这里清理所有通知，因为这会影响到其他可能正在使用通知系统的组件
  // 通知系统的清理应该由应用层面决定，而不是在组件层面
})

// 开始关闭动画（用于自动关闭）
function startCloseAnimation(id: string) {
  // 如果通知已经开始关闭或不可见，则不处理
  if (closingNotifications.value.has(id) || !visibleNotifications.value.has(id)) {
    return
  }

  // 添加到正在关闭的列表
  closingNotifications.value.add(id)

  // 延迟后真正移除通知
  setTimeout(() => {
    removeNotification(id)
    closingNotifications.value.delete(id)
    visibleNotifications.value.delete(id)
  }, 300) // 与CSS动画时间匹配
}

// 处理鼠标进入事件（暂停计时器）
function handleMouseEnter(id: string) {
  pauseTimer(id)
}

// 处理鼠标离开事件（恢复计时器）
function handleMouseLeave(id: string) {
  resumeTimer(id)
}
</script>

<style scoped>
.notification-item {
  will-change: transform, opacity;
}

/* 滑入动画 */
.notification-enter-active {
  transition: all 0.3s ease-out;
}

.notification-leave-active {
  transition: all 0.3s ease-in;
}

.notification-enter-from {
  transform: translateY(-100%);
  opacity: 0;
}

.notification-leave-to {
  transform: translateY(-100%);
  opacity: 0;
}

.notification-move {
  transition: transform 0.3s ease;
}
</style>
